package org.luxor.commons.core.config.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置
 *
 * @author Mr.yan @date 2020/2/12
 */
@ConfigurationProperties(prefix = ThreadPoolProperties.PREFIX)
public class ThreadPoolProperties {
    public static final String PREFIX = "spring.thread-pool";

    private final int DEFAULT_CORE_POOL_SIZE = Math.max(1, Runtime.getRuntime().availableProcessors() + 1);
    private final int DEFAULT_MAX_POOL_SIZE = DEFAULT_CORE_POOL_SIZE * 2;
    private final int DEFAULT_QUEUE_CAPACITY = (int) (DEFAULT_CORE_POOL_SIZE / 0.75) * 5;
    private final int DEFAULT_KEEP_ALIVE_SECONDS = 60;
    private final Boolean DEFAULT_WAIT_FOR_JOBS_TO_COMPLETE_ON_SHUTDOWN = Boolean.TRUE;
    private final int DEFAULT_AWAIT_TERMINATION_SECONDS = 30;
    private final RejectedStrategy DEFAULT_REFUSAL_STRATEGY = RejectedStrategy.ABORT_POLICY;

    /**
     * 核心线程数,默认值: CPU虚拟内核数 + 1
     */
    private int corePoolSize;
    /**
     * 最大线程数,默认值: (CPU虚拟内核数+1) * 2
     */
    private int maxPoolSize;
    /**
     * 缓冲队列大小,默认值: (CPU虚拟内核数 / 0.75) * 5
     */
    private int queueCapacity;
    /**
     * 允许线程空闲时间（单位：秒）
     */
    private int keepAliveSeconds;
    /**
     * 等待所有线程执行完再销毁线程池
     */
    private boolean waitForJobsToCompleteOnShutdown;
    /**
     * 最长等待多久再销毁线程池（单位：秒）
     */
    private int awaitTerminationSeconds;

    /**
     * 拒绝策略( AbortPolicy | CallerRunsPolicy | DiscardPolicy | DiscardOldestPolicy )
     */
    private RejectedStrategy rejectedStrategy;

    public ThreadPoolProperties() {
        this.corePoolSize = DEFAULT_CORE_POOL_SIZE;
        this.maxPoolSize = DEFAULT_MAX_POOL_SIZE;
        this.queueCapacity = DEFAULT_QUEUE_CAPACITY;
        this.keepAliveSeconds = DEFAULT_KEEP_ALIVE_SECONDS;
        this.waitForJobsToCompleteOnShutdown = DEFAULT_WAIT_FOR_JOBS_TO_COMPLETE_ON_SHUTDOWN.booleanValue();
        this.awaitTerminationSeconds = DEFAULT_AWAIT_TERMINATION_SECONDS;
        this.rejectedStrategy = DEFAULT_REFUSAL_STRATEGY;
    }

    public int getCorePoolSize() {
        return corePoolSize;
    }

    public void setCorePoolSize(int corePoolSize) {
        this.corePoolSize = corePoolSize;
    }

    public int getMaxPoolSize() {
        return maxPoolSize;
    }

    public void setMaxPoolSize(int maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
    }

    public int getQueueCapacity() {
        return queueCapacity;
    }

    public void setQueueCapacity(int queueCapacity) {
        this.queueCapacity = queueCapacity;
    }

    public int getKeepAliveSeconds() {
        return keepAliveSeconds;
    }

    public void setKeepAliveSeconds(int keepAliveSeconds) {
        this.keepAliveSeconds = keepAliveSeconds;
    }

    public boolean isWaitForJobsToCompleteOnShutdown() {
        return waitForJobsToCompleteOnShutdown;
    }

    public void setWaitForJobsToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
        this.waitForJobsToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
    }

    public int getAwaitTerminationSeconds() {
        return awaitTerminationSeconds;
    }

    public void setAwaitTerminationSeconds(int awaitTerminationSeconds) {
        this.awaitTerminationSeconds = awaitTerminationSeconds;
    }

    public RejectedStrategy getRejectedStrategy() {
        return rejectedStrategy;
    }

    public void setRejectedStrategy(RejectedStrategy rejectedStrategy) {
        this.rejectedStrategy = rejectedStrategy;
    }

    public RejectedExecutionHandler getRejectedExecutionHandler() {
        switch (this.getRejectedStrategy()) {
            case CALLER_RUNS_POLICY:
                return new ThreadPoolExecutor.CallerRunsPolicy();
            case DISCARD_POLICY:
                return new ThreadPoolExecutor.DiscardPolicy();
            case DISCARD_OLDEST_POLICY:
                return new ThreadPoolExecutor.DiscardOldestPolicy();
            default:
                return new ThreadPoolExecutor.AbortPolicy();

        }
    }


}
